﻿using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using System.Windows.Media;
using Algoritmia.DataStructures.Lists;
using Algoritmia.Problems.CoinChange;

namespace Demos.CoinChange
{
    public class Moneda
    {
        public Moneda(int valor)
        {
            if (valor < 100)
            {
                Diametro = 30;
                BordeColor = Brushes.Black;
                BordeGrosor = 3;
                Fondo = Brushes.Goldenrod;
                Valor = valor + "c";
            }
            else
            {
                Diametro = 35;
                BordeColor = Brushes.Goldenrod;
                BordeGrosor = 4;
                Fondo = Brushes.LightGray;
                Valor = (valor/100) + "€";
            }
        }

        public double Diametro { get; private set; }
        public int BordeGrosor { get; private set; }
        public Brush BordeColor { get; private set; }
        public Brush Fondo { get; private set; }
        public string Valor { get; private set; }
    }

    internal class ViewModel : INotifyPropertyChanged
    {
        private readonly IGreedyCoinChanger _model;
        private readonly ArrayList<int> _valoresMonedas;
        private double _contador;
        private ObservableCollection<Moneda> _monedas;

        public ViewModel(IGreedyCoinChanger model)
        {
            _model = model;
            _valoresMonedas = new ArrayList<int> {200, 100, 50, 20, 10, 5, 2, 1};
            Monedas = new ObservableCollection<Moneda>();
            Contador = 0;
            AumentarCommand = new RelayCommand(() => Contador++, () => true);
            Aumentar2Command = new RelayCommand(() => Contador = Contador + 2, () => true);
            Aumentar5Command = new RelayCommand(() => Contador = Contador + 5, () => true);
            Aumentar10Command = new RelayCommand(() => Contador = Contador + 10, () => true);
            Aumentar20Command = new RelayCommand(() => Contador = Contador + 20, () => true);
            Aumentar50Command = new RelayCommand(() => Contador = Contador + 50, () => true);
            Aumentar100Command = new RelayCommand(() => Contador = Contador + 100, () => true);
            Aumentar200Command = new RelayCommand(() => Contador = Contador + 200, () => true);
            DisminuirCommand = new RelayCommand(() => Contador--, () => Contador > 0);
            ResetCommand = new RelayCommand(Reset, () => true);
            ChangeCommand = new RelayCommand(Change, () => true);
        }

        private double Contador
        {
            get { return _contador; }
            set
            {
                _contador = value;
                NotifyPropertyChanged("Marcador");
            }
        }

        public string Marcador
        {
            get { return (_contador/100).ToString("0.00"); }
        }

        public ObservableCollection<Moneda> Monedas
        {
            get { return _monedas; }
            set
            {
                _monedas = value;
                NotifyPropertyChanged("Monedas");
            }
        }

        public ICommand AumentarCommand { get; private set; }
        public ICommand Aumentar2Command { get; private set; }
        public ICommand Aumentar5Command { get; private set; }
        public ICommand Aumentar10Command { get; private set; }
        public ICommand Aumentar20Command { get; private set; }
        public ICommand Aumentar50Command { get; private set; }
        public ICommand Aumentar100Command { get; private set; }
        public ICommand Aumentar200Command { get; private set; }
        public ICommand DisminuirCommand { get; private set; }
        public ICommand ResetCommand { get; private set; }
        public ICommand ChangeCommand { get; private set; }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private void Change()
        {
            Monedas.Clear();
            IList<int> cambio = _model.Change((int) Contador);
            for (int i = 0; i < _valoresMonedas.Count; i++)
            {
                for (int j = 0; j < cambio[i]; j++)
                {
                    Monedas.Add(new Moneda(_valoresMonedas[i]));
                }
            }
        }

        private void Reset()
        {
            Contador = 0;
            Monedas.Clear();
        }
    }
}